<!doctype html>
<!--
Copyright (c) 2014 The Polymer Project Authors. All rights reserved.
This code may only be used under the BSD style license found at http://polymer.github.io/LICENSE.txt
The complete set of authors may be found at http://polymer.github.io/AUTHORS.txt
The complete set of contributors may be found at http://polymer.github.io/CONTRIBUTORS.txt
Code distributed by Google as part of the polymer project is also
subject to an additional IP rights grant found at http://polymer.github.io/PATENTS.txt
-->
<html>
  <head>
    <title>unbind</title>
    <script src="../../../webcomponentsjs/webcomponents.js"></script>
    <link rel="import" href="../../polymer.html">
    <script src="../../../tools/test/htmltest.js"></script>
    <script src="../../../tools/test/chai/chai.js"></script>
  </head>
  <body>

  <x-test></x-test>

  <polymer-element name="x-test" attributes="bar">
    <template>
    </template>
    <script>
      Polymer('x-test', {
        foo: '',
        forceReady: true,
        ready: function() {},
        fooChanged: function() {
          this.fooWasChanged = true;
        },
        barChanged: function() {
          this.validBar = this.bar;
        },
        isBarValid: function() {
          return this.validBar == this.bar;
        }
      });
    </script>
  </polymer-element>

  <script>
     function testAsync(tests, delay, args) {
       if (tests.length) {
         CustomElements.takeRecords();
         setTimeout(function() {
           var lastArgs = tests.shift().apply(null, args || []);
           testAsync(tests, delay, lastArgs);
         }, delay);
       } else {
         done();
       }
     }

    document.addEventListener('polymer-ready', function() {
      xTest = document.querySelector('x-test');
      xTest.foo = 'bar';
      Platform.flush();

      function assertNoObservers() {
        chai.assert.equal(Observer._allObserversCount, 0);
      }

      function assertSomeObservers() {
        chai.assert.isTrue(Observer._allObserversCount > 0);
      }

      testAsync([
        function() {
          chai.assert.ok(!xTest._unbound,
            'element is bound when inserted');
          chai.assert.isTrue(xTest.fooWasChanged,
            'element is actually bound');
          assertSomeObservers();
          xTest.parentNode.removeChild(xTest);
        },
        function() {
          chai.assert.isTrue(xTest._unbound,
            'element is unbound when removed');
          assertNoObservers();
          return [document.createElement('x-test')];
        },
        function(node) {
          chai.assert.isUndefined(node._unbound,
            'element is bound when not inserted');
          node.foo = 'bar';
          assertSomeObservers();
          Platform.flush();
          return [node];
        },
        function(node) {
          chai.assert.isTrue(node.fooWasChanged, 'node is actually bound');
          node.unbindAll();
          var n = document.createElement('x-test');
          document.body.appendChild(n);
          return [n];
        },
        function(node) {
          node.preventDispose = true;
          node.parentNode.removeChild(node);
          return [node];
        },
        function(node) {
          chai.assert.ok(!node._unbound,
            'element is bound when preventDispose is true');
          assertSomeObservers();
          node.unbindAll();
          chai.assert.isTrue(node._unbound,
            'element is unbound when unbindAll is called');
          assertNoObservers();
          var n = document.createElement('x-test');
          document.body.appendChild(n);
          return [n];
        },
        function(node) {
          chai.assert.ok(!node._unbound,
            'element is bound when manually inserted');
          assertSomeObservers();
          document.body.removeChild(node);
          return [node];
        },
        function(node) {
          chai.assert.isTrue(node._unbound,
            'element is unbound when manually removed is called');
          assertNoObservers();
        }
      // TODO(sorvell): In IE, the unbind time is indeterminate, so wait an
      // extra beat.
      ], 50);
    });
  </script>
  </body>
</html>
